<template>
  <div id="viewport" class="holder" data-type="viewport">
    <div
      :style="{
        height: page.height*4 + 'px',
        width: page.width*4 + 'px',
        backgroundImage: 'url('+backImg+')'
      }"
      class="screen"
    >
      <!-- 组件 -->
      <component
        :is="val.type"
        v-for="val in widgetStore"
        :key="val.uuid"
        :class="{'active': widgetId === val.uuid}"
        :data-title="val.type"
        :data-type="val.type"
        :data-uuid="val.uuid"
        :val="val"
        class="layer"
      ></component>

      <!-- 参考线 -->
      <!-- <ref /> -->

      <!-- 尺寸控制器 -->
      <control/>
    </div>
  </div>
</template>

<script>
import control from './size-control.vue'

export default {
  components: {
    control // 尺寸控制
  },
  data() {
    return {}
  },
  computed: {
    // 已添加的组件
    widgetStore() {
      return this.$store.state.printTemplate.page.tempItems
    },
    // 背景图地址
    backImg() {
      return this.$store.state.printTemplate.page.imageUrl ? this.$store.state.printTemplate.page.imageUrl : ''
    },

    // 画布高度
    page() {
      return this.$store.state.printTemplate.page
    },
    // 选中项id
    widgetId() {
      return this.$store.state.printTemplate.uuid
    }
  },
  mounted() {
    // 采用事件代理的方式监听元件的选中操作
    document.getElementById('viewport').addEventListener('mousedown', this.handleSelection, false)

    // 绑定键盘上下左右键用于元件的移动
    document.addEventListener(
      'keydown',
      (e) => {
        e.stopPropagation()
        var target = this.$store.state.printTemplate.activeElement
        // 左
        if (e.keyCode === 37 && target.left) {
          target.left -= 1
          return
        }
        // 上
        if (e.keyCode === 38 && target.top) {
          e.preventDefault()
          target.top -= 1
          return
        }
        // 右
        if (e.keyCode === 39 && target.left) {
          target.left += 1
          return
        }
        // 下
        if (e.keyCode === 40 && target.top) {
          e.preventDefault()
          target.top += 1
        }
      },
      true
    )
  },
  methods: {
    /**
     * 目标元素获得焦点
     */
    handleSelection(e) {
      var target = this.selectTarget(e.target)
      if (target) {
        var uuid = target.getAttribute('data-uuid')
        // 设置选中元素
        this.$store.commit('printTemplate/select', {
          uuid: uuid || -1
        })
        // 绑定移动事件：除背景图以外的元件才能移动
        target = this.$store.state.printTemplate.activeElement
        if (target.dragable) {
          this.initmovement(e) // 参见 mixins
        }
      } else {
        // 取消选中元素
        this.$store.commit('printTemplate/select', {
          uuid: -1
        })
      }
    },
    /**
     * 获得选中的目标，如果没有返回false
     */
    selectTarget(target) {
      let type = target.getAttribute('data-type')
      if (type) {
        if (type === 'viewport') {
          return false
        } else {
          return target
        }
      } else {
        return this.selectTarget(target.parentNode)
      }
    },
    /**
     * 初始化鼠标拖拽事件
     * @param {*} e
     */
    initmovement(e) {
      var target = this.$store.state.printTemplate.activeElement

      // 设置移动状态初始值
      this.$store.commit('printTemplate/initmove', {
        startX: e.pageX,
        startY: e.pageY,
        originX: target.left,
        originY: target.top
      })

      // 绑定鼠标移动事件
      document.addEventListener('mousemove', this.handlemousemove, true)

      // 取消鼠标移动事件
      document.addEventListener('mouseup', this.handlemouseup, true)
    },
    /**
     * 鼠标移动
     * @param {*} e
     */
    handlemousemove(e) {
      e.stopPropagation()
      e.preventDefault()

      this.$store.commit('printTemplate/move', {
        x: e.pageX,
        y: e.pageY
      })
    },
    /**
     * 鼠标up
     */
    handlemouseup() {
      document.removeEventListener('mousemove', this.handlemousemove, true)
      document.removeEventListener('mouseup', this.handlemouseup, true)
      this.$store.commit('printTemplate/stopmove')
    }
  }
}
</script>

<style scoped>
.holder {
  display: flex;
  justify-content: center;
  overflow: auto;
  font-size: 0;
  border: 1px solid #f5f5f5;
  border-width: 0 1px;
  background-image: linear-gradient(45deg, #f5f5f5 25%, transparent 0, transparent 75%, #f5f5f5 0),
  linear-gradient(45deg, #f5f5f5 25%, transparent 0, transparent 75%, #f5f5f5 0);
  background-position: 0 0, 13px 13px;
  background-size: 26px 26px;
}

.screen {
  margin: 25px auto;
  transform-origin: center top;
  position: relative;
  box-shadow: 0 0 5px 1px #cccccc;
  background-color: #ffffff;
  background-repeat: no-repeat;
}
</style>
